package class4;

/**
 * https://www.nowcoder.com/practice/02ae5ccb63064bbdb2366417d8b70ff3
 * 不用任何比较判断找出两个数中较大的数
 * 解题思路：
 * <p>
 * 解法1思路：获取 a-b 的“符号位”，通过符号正负值，判断 a和 b 的大小
 * 解法2思路：还是获取 a-b 的符号位，但计算最大值时，a-(a-b)*c
 * <p>
 * 扩展：
 * 如果越界，怎么办？
 * 解法3
 */
public class Code13_getMax {
    public static void main(String[] args) {
        //System.out.println(3 >>> 31);
        //System.out.println(-12 >>> 31);

        int a = 23;
        int b = 33;
        // 解法1
        int ans = getMax(a, b);
        System.out.println("ans = " + ans);

        // 解法2
        int ans2 = getMax2(a, b);
        System.out.println("ans2 = " + ans2);

        // 解法3
        int ans3 = getMax3(a, b);
        System.out.println("ans3 = " + ans3);
    }

    // 获取
    public static int getMax(int a, int b) {
        int c = a - b;
        int scA = sign(c);
        int scB = flip(scA);
        return scA * a + scB * b;
    }

    // 步骤1
    // n >>> 31 获取n的符号位， 1：负数， 0：正数或0
    public static int sign(int n) {
        return flip(n >>> 31);
    }

    // 步骤2
    // 对标识位进行异或，变成 0：负数 1：整数或0
    public static int flip(int n) {
        return n ^ 1;
    }

    /**
     * 1.获取差值的符号位： (a-b) >>> 31
     * 2.如果c为负数=0，则 (a-b)*c = 0，返回a
     * 3.如果c为非负数=1，则 a-(a-b)*1 = a-a+b，返回b
     */
    public static int getMax2(int a, int b) {
        int c = (a - b) >>> 31;
        return a - (a - b) * c;
    }

    public static int getMax3(int a, int b) {
        int c = a - b; // c可能溢出
        // a的符号，b的符号,c的符号
        int sa = sign(a);
        int sb = sign(b);
        int sc = sign(c);

        // 判断 a 和 b 的符号是否一样
        // 如果 sa == sb（即 a 和 b 符号相同），则 diffAB = 0
        // 如果 sa != sb（即 a 和 b 符号不同），则 diffAB = 1。
        int diffAB = sa ^ sb;

        // 如果 diffAB = 0，则 sameSAB = 1，表示 a 和 b 的符号相同。
        // 如果 diffAB = 1，则 sameSAB = 0，表示 a 和 b 的符号不同。
        int sameSAB = flip(diffAB);

        // returnA 根据 a 和 b 符号的比较来决定。如果 a 和 b 符号不同，则返回 a 的符号 sa；如果 a 和 b 符号相同，则返回 a - b 的符号 sc。
        // 如果 a 和 b 符号不同，diffAB = 1，那么 returnA = sa，即返回 a 的符号
        // 如果 a 和 b 符号相同，diffAB = 0，sameSAB = 1，那么 returnA = sc，即返回 a - b 的符号。
        int returnA = diffAB *  sa + sameSAB * sc;

        // 如果 returnA = 1，则 returnB = 0。
        // 如果 returnA = 0，则 returnB = 1。
        int returnB = flip(returnA);
        // a 和 b 的符号相同的时候返回 a，否则返回 b
        return a * returnA + b * returnB;
    }

}
